<?php

namespace iBrand\Shop\Server\Controllers\V2;

use Carbon\Carbon;
use iBrand\Component\Balance\Repository\BalanceRepository;
use iBrand\Component\Payment\Models\Payment;
use iBrand\Component\Recharge\Repositories\RechargeRuleRepository;
use iBrand\Shop\Core\Models\Balance;
use iBrand\Shop\Core\Models\BalanceOrder;
use iBrand\Shop\Core\Models\User;
use iBrand\Shop\Core\Repositories\BalanceOrderRepository;
use iBrand\Shop\Core\Repositories\ClerkBalanceOrderRepository;
use iBrand\Shop\Core\Repositories\UserShopRepository;
use iBrand\Common\Controllers\Controller;
use iBrand\Shop\Server\Resources\BalanceOrderResource;
use Illuminate\Http\Request;
use Validator;
use DB;

class BalanceController extends Controller
{
    protected $balanceRepository;
    protected $rechargeRuleRepository;
    protected $userShopRepository;
    protected $balanceOrderRepository;
    protected $clerkBalanceOrderRepository;

    public function __construct(
        BalanceRepository $balanceRepository,
        RechargeRuleRepository $rechargeRuleRepository,
        UserShopRepository $userShopRepository,
        BalanceOrderRepository $balanceOrderRepository,
        ClerkBalanceOrderRepository $clerkBalanceOrderRepository)
    {
        $this->balanceRepository = $balanceRepository;
        $this->rechargeRuleRepository = $rechargeRuleRepository;
        $this->userShopRepository = $userShopRepository;
        $this->balanceOrderRepository = $balanceOrderRepository;
        $this->clerkBalanceOrderRepository = $clerkBalanceOrderRepository;
    }

    public function getSchemes()
    {
        $lists = $this->rechargeRuleRepository->getEffective();

        return $this->success($lists);
    }

    public function checkout(Request $request)
    {
        $input = $request->except('_token', 'file');
        $rules = [
            'user_id' => 'required|integer',
            'recharge_rule_id' => 'required|integer',
        ];
        $message = [
            "required" => ":attribute 不能为空",
            "integer" => ":attribute 必须为整数",
        ];
        $attributes = [
            'user_id' => '充值用户',
            'recharge_rule_id' => '充值方案',
        ];

        $validator = Validator::make($input, $rules, $message, $attributes);
        if ($validator->fails()) {

            return $this->failed($validator->messages()->first());
        }

        try {

            $rule = $this->rechargeRuleRepository->findWhere(['id' => $input['recharge_rule_id']])->first();
            if (!$rule) {
                throw new \Exception('充值方案不存在');
            }

            $clerk = auth('clerk')->user();

            /*$userShop = $this->userShopRepository->findWhere(['user_id' => $input['user_id'], 'shop_id' => $clerk->shop_id])->first();
            if (!$userShop) {
                throw new \Exception('用户不存在');
            }

            $user    = $userShop->user;*/
            \Log::info($input['user_id']);
            $user = User::find($input['user_id']);
            $balance = $this->balanceRepository->getSum($user->id);
            $order = $this->balanceOrderRepository->create([
                'user_id' => $user->id,
                'order_no' => build_order_no('R'),
                'amount' => $rule->amount,
                'pay_amount' => $rule->payment_amount,
                'recharge_rule_id' => $rule->id,
            ]);

            return $this->success(['order' => $order, 'user' => $user, 'balance' => $balance]);
        } catch (\Exception $exception) {
            \Log::info($exception->getTraceAsString());
            return $this->failed($exception->getMessage());
        }
    }

    public function paid(Request $request)
    {
        $input = $request->except('_token', 'file');
        $rules = [
            'order_no' => 'required',
            'total_amount' => 'required',
            'actual' => 'required|integer',//实收
            'remaining' => 'required',//找零
            'payments' => 'required|array',
        ];
        $message = [
            "required" => ":attribute 不能为空",
            "integer" => ":attribute 必须为整数",
        ];
        $attributes = [
            'order_no' => '订单编号',
            'payments' => '支付信息',
            'total_amount' => '总金额',
        ];

        $validator = Validator::make($input, $rules, $message, $attributes);
        if ($validator->fails()) {

            return $this->failed($validator->messages()->first());
        }

        $order = $this->balanceOrderRepository->findWhere(['order_no' => $input['order_no'], 'pay_status' => 0])->first();
        if (!$order) {
            return $this->failed('订单不存在');
        }

        $rule = $order->recharge()->where('status', 1)->orWhere('status', 2)->first();
        if (!$rule) {
            return $this->failed('充值方案不存在');
        }

        $payments_sum = array_sum(array_column($input['payments'], 'amount'));
        if (($input['actual'] - $input['remaining']) != $input['total_amount'] || ($payments_sum - $input['remaining']) != $input['total_amount']) {
            return $this->failed('实收金额、找零金额错误');
        }

        if ($input['total_amount'] != $rule->payment_amount) {
            return $this->failed('支付金额错误');
        }

        $clerk = auth('clerk')->user();
        try {

            DB::beginTransaction();

            foreach ($input['payments'] as $payment) {
                $payment = new Payment([
                    'order_id' => $order->id,
                    'order_type' => BalanceOrder::class,
                    'channel' => $payment['key'],
                    'amount' => $payment['amount'],
                    'status' => Payment::STATUS_COMPLETED,
                    'paid_at' => Carbon::now(),
                ]);

                $payment->save();
            }

            $this->clerkBalanceOrderRepository->create([
                'balance_order_id' => $order->id,
                'clerk_id' => $clerk->id,
                'shop_id' => $clerk->shop_id,
                'actual' => $input['actual'],
                'remaining' => $input['remaining'],
            ]);

            $order->pay_status = 1;
            $order->pay_time = Carbon::now();
            $order->save();

            $balance = $this->balanceRepository->getSum($order->user_id);
            $this->balanceRepository->addRecord([
                'user_id' => $order->user_id,
                'type' => Balance::TYPE_RECHARGE,
                'note' => isset($input['note']) && $input['note'] ? $input['note'] : '充值',
                'value' => $order->amount,
                'current_balance' => $balance + $order->amount,
                'origin_id' => $order->id,
                'origin_type' => BalanceOrder::class,
            ]);

            DB::commit();

            return $this->success(['order' => $order, 'actual' => $input['actual'], 'remaining' => $input['remaining']]);
        } catch (\Exception $exception) {
            DB::rollBack();

            \Log::info($exception->getTraceAsString());

            return $this->failed($exception->getMessage());
        }
    }

    public function list()
    {
        $limit = request('limit') ? request('limit') : 15;

        $where['pay_status'] = 1;
        if (request('user_id')) {
            $where['user_id'] = request('user_id');
        }

        if (request('order_no')) {
            $where['order_no'] = ['like', '%' . request('order_no') . '%'];
        }

        $clerk = auth('clerk')->user();
        $shop_id = $clerk->shop_id;
        $list = $this->balanceOrderRepository->scopeQuery(function ($query) use ($where, $shop_id) {
            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query->where($key, $value);
                    }
                }
            }

            return $query->whereHas('clerkBalance', function ($query) use ($shop_id) {
                return $query->where('shop_id', $shop_id);
            })->with('user')->orderBy('created_at', 'DESC');
        })->paginate($limit);

        return $this->paginator($list, BalanceOrderResource::class);
    }

    public function detail($order_no)
    {
        $order = $this->balanceOrderRepository->with(['user', 'rule'])->findWhere(['pay_status' => 1, 'order_no' => $order_no])->first();
        if (!$order) {
            return $this->failed('订单不存在');
        }

        $payments = $order->payments()->where('order_type', BalanceOrder::class)->where('status', Payment::STATUS_COMPLETED)->get();

        $actual = 0;
        $remaining = 0;

        if ($order->clerkBalance) {
            $actual = $order->clerkBalance->actual;
            $remaining = $order->clerkBalance->remaining;
        }

        return $this->success([
            'order' => $order,
            'payments' => $payments,
            'clerk' => auth('clerk')->user(),
            'actual' => $actual,
            'remaining' => $remaining,
        ]);
    }
}